package com.xu.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xu.base.enums.ResponseCodeEnum;
import com.xu.base.utils.AssertUtils;
import com.xu.base.utils.TreeNodeUtils;
import com.xu.redis.service.SequenceService;
import com.xu.security.utils.SecurityUtils;
import com.xu.system.enums.SequenceEnum;
import com.xu.system.model.convert.MenuConvert;
import com.xu.system.model.entity.SysMenu;
import com.xu.system.model.pojo.menu.*;
import com.xu.system.service.IMenuService;
import com.xu.system.service.db.ISysMenuService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 菜单服务
 *
 * @Author: 许乾伟
 * @Date: 2024/12/17 16:30
 */
@Service
public class MenuServiceImpl implements IMenuService {
    @Resource
    ISysMenuService sysMenuService;
    @Resource
    MenuConvert menuConvert;
    @Resource
    SequenceService sequenceService;
    @Override
    public Boolean add(AddMenuReq req) {
        verifyMenuParentId(req.getParentId());
        SysMenu sysMenu = menuConvert.toSysMenu(req);
        sysMenu.setMenuCode(sequenceService.generateCode(SequenceEnum.MENU_CODE_RULE));
        return sysMenuService.save(sysMenu);
    }

    @Override
    public Boolean edit(EditMenuReq req) {
        verifyMenuParentId(req.getParentId());
        SysMenu sysMenu = sysMenuService.getById(req.getMenuId());
        AssertUtils.isNull(sysMenu,ResponseCodeEnum.DATA_FAILED,"未查询到菜单数据，无法编辑");
        sysMenu.setMenuName(req.getMenuName())
                .setParentId(req.getParentId())
                .setPath(req.getPath())
                .setIsFrame(req.getIsFrame())
                .setPerms(req.getPerms())
                .setIcon(req.getIcon())
                .setSort(req.getSort())
                .setRemark(req.getRemark())
                .setStatus(req.getStatus())
                .setUpdateBy(SecurityUtils.getUserId())
                .setUpdateTime(LocalDateTime.now());
        return sysMenuService.updateById(sysMenu);
    }

    @Override
    public Boolean del(Long menuId) {
        SysMenu sysMenu = sysMenuService.getById(menuId);
        AssertUtils.isNull(sysMenu, ResponseCodeEnum.DATA_FAILED, "未查询到菜单数据，无法编辑");
        //检查是否有子菜单
        long count = sysMenuService.count(new QueryWrapper<SysMenu>()
                .eq(SysMenu.PARENT_ID, menuId)
                .eq(SysMenu.IS_DELETE, Boolean.FALSE));
        AssertUtils.isTrue(count > 0L, ResponseCodeEnum.HANDEL_FAILED, "必须先删除子级菜单");
        sysMenu.setIsDelete(Boolean.TRUE)
                .setUpdateBy(SecurityUtils.getUserId())
                .setUpdateTime(LocalDateTime.now());
        return sysMenuService.updateById(sysMenu);
    }

    @Override
    public MenuVo detail(Long menuId) {
        SysMenu sysMenu = sysMenuService.getById(menuId);
        AssertUtils.isNull(sysMenu, ResponseCodeEnum.DATA_FAILED, "未查询到菜单数据");
        return menuConvert.toMenuVo(sysMenu);
    }

    @Override
    public List<MenuTreeVo> queryMenuTreeList(QueryMenuReq req) {
        List<SysMenu> list = sysMenuService.list(new QueryWrapper<SysMenu>()
                .like(StringUtils.hasText(req.getMenuName()),SysMenu.MENU_NAME,req.getMenuName())
                .eq(req.getStatus()!=null,SysMenu.STATUS,req.getStatus())
                .eq(SysMenu.IS_DELETE,Boolean.FALSE)
                .orderByAsc(SysMenu.SORT));
        if (list.isEmpty()){
            return new ArrayList<>();
        }
        List<MenuTreeVo> menuTreeVoList = menuConvert.toMenuTreeVoList(list);
        return TreeNodeUtils.buildTree(menuTreeVoList);
    }

    @Override
    public List<MenuSimpleTreeVo> querySimpleMenuTree() {
        QueryWrapper<SysMenu> wrapper = new QueryWrapper<SysMenu>()
                .eq(SysMenu.IS_DELETE, Boolean.FALSE)
                .orderByAsc(SysMenu.SORT);
        List<SysMenu> list = sysMenuService.list(wrapper);
        if (list.isEmpty()){
            return new ArrayList<>();
        }
        List<MenuSimpleTreeVo> menuSimpleTreeVoList = menuConvert.toMenuSimpleTreeVoList(list);
        return TreeNodeUtils.buildTree(menuSimpleTreeVoList);
    }

    /**
     * 验证菜单是否存在有效的父级菜单
     * @param parentId
     */
    private void verifyMenuParentId(Long parentId) {
        if (parentId != 0L) {
            SysMenu sysMenu = sysMenuService.getById(parentId);
            AssertUtils.isNull(sysMenu, ResponseCodeEnum.DATA_FAILED, "父菜单不存在");
        }
    }
}
